/*
 * A V4L2 driver for hm8030 cameras.
 *
 */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/videodev2.h>
#include <linux/clk.h>
#include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h>
#include <media/v4l2-mediabus.h>
#include <linux/io.h>


#include "camera.h"


MODULE_AUTHOR("Chomoly");
MODULE_DESCRIPTION("A low-level driver for hm8030 sensors");
MODULE_LICENSE("GPL");

//for internel driver debug
#define DEV_DBG_EN      1 
#if(DEV_DBG_EN == 1)    
#define vfe_dev_dbg(x,arg...) printk("[hm8030]"x,##arg)
#else
#define vfe_dev_dbg(x,arg...) 
#endif
#define vfe_dev_err(x,arg...) printk("[hm8030]"x,##arg)
#define vfe_dev_print(x,arg...) printk("[hm8030]"x,##arg)

#define LOG_ERR_RET(x)  { \
                          int ret;  \
                          ret = x; \
                          if(ret < 0) {\
                            vfe_dev_err("error at %s\n",__func__);  \
                            return ret; \
                          } \
                        }

//define module timing
#define MCLK              (12*1000*1000)
#define VREF_POL          V4L2_MBUS_VSYNC_ACTIVE_LOW
#define HREF_POL          V4L2_MBUS_HSYNC_ACTIVE_HIGH
#define CLK_POL           V4L2_MBUS_PCLK_SAMPLE_RISING
#define V4L2_IDENT_SENSOR 0x0364
#define SENSOR_NAME "hm8030"

#define regval_list reg_list_a16_d8

#define REG_TERM 0xfffe
#define VAL_TERM 0xfe
#define REG_DLY  0xcdcd			//different from other reg delay macro

/*
 * Our nominal (default) frame rate.
 */
#ifdef FPGA
#define SENSOR_FRAME_RATE 15
#else
#define SENSOR_FRAME_RATE 30
#endif

/*
 * The hm8030 sits on i2c with ID 0x6c
 */
#define I2C_ADDR 0x20
int hm8030_sensor_vts;

static struct v4l2_subdev *glb_sd;

/*
 * Information we maintain about a known sensor.
 */
struct sensor_format_struct;  /* coming later */

struct cfg_array { /* coming later */
  struct regval_list * regs;
  int size;
};

static inline struct sensor_info *to_state(struct v4l2_subdev *sd)
{
	return container_of(sd, struct sensor_info, sd);
}


/*
 * The default register settings
 *
 */
static struct regval_list sensor_default_regs[] = {

};

//for capture                                                                         
static struct regval_list sensor_hxga_regs[] = { //3264x2448@ 15fps 2lane
	{0x0103 ,0x01},//
	{0xffff ,0x01},//		 ;MCU bypass;
	{0xcdcd ,200},
	{0x8500 ,0x03},//		 ;Enable Ram and enable Write;
	{0x9000 ,0xF0},//
	{0x9001 ,0x90},//
	{0x9002 ,0x52},//
	{0x9003 ,0x00},//
	{0x9004 ,0xF0},//
	{0x9005 ,0x02},//
	{0x9006 ,0x13},//
	{0x9007 ,0x1A},//
	{0x9008 ,0x90},//
	{0x9009 ,0x30},//
	{0x900A ,0x6c},//
	{0x900B ,0xE0},//
	{0x900C ,0x90},//
	{0x900D ,0x00},//
	{0x900E ,0x02},//
	{0x900F ,0xF0},//
	{0x9010 ,0x22},//
	{0x9011 ,0x24},//
	{0x9012 ,0xFE},//
	{0x9013 ,0xF0},//
	{0x9014 ,0x90},//
	{0x9015 ,0xA5},//
	{0x9016 ,0xB5},//
	{0x9017 ,0xE0},//
	{0x9018 ,0x34},//
	{0x9019 ,0xFF},//
	{0x901A ,0x02},//
	{0x901B ,0x12},//
	{0x901C ,0x3F},//
	{0x901D ,0x90},//
	{0x901E ,0xA6},//
	{0x901F ,0x49},//
	{0x9020 ,0xE0},//
	{0x9021 ,0xFF},//
	{0x9022 ,0x64},//
	{0x9023 ,0x01},//
	{0x9024 ,0x60},//
	{0x9025 ,0x05},//
	{0x9026 ,0xEF},//
	{0x9027 ,0x64},//
	{0x9028 ,0x04},//
	{0x9029 ,0x70},//
	{0x902A ,0x7D},//
	{0x902B ,0x90},//
	{0x902C ,0xA5},//
	{0x902D ,0xB9},//
	{0x902E ,0xE0},//
	{0x902F ,0xFF},//
	{0x9030 ,0xC3},//
	{0x9031 ,0x94},//
	{0x9032 ,0x80},//
	{0x9033 ,0x50},//
	{0x9034 ,0x13},//
	{0x9035 ,0xA3},//
	{0x9036 ,0x74},//
	{0x9037 ,0x4D},//
	{0x9038 ,0xF0},//
	{0x9039 ,0xA3},//
	{0x903A ,0x74},//
	{0x903B ,0xB3},//
	{0x903C ,0xF0},//
	{0x903D ,0xA3},//
	{0x903E ,0x74},//
	{0x903F ,0x40},//
	{0x9040 ,0xF0},//
	{0x9041 ,0xA3},//
	{0x9042 ,0x74},//
	{0x9043 ,0x9B},//
	{0x9044 ,0xF0},//
	{0x9045 ,0x02},//
	{0x9046 ,0x51},//
	{0x9047 ,0x1F},//
	{0x9048 ,0xEF},//
	{0x9049 ,0xC3},//
	{0x904A ,0x94},//
	{0x904B ,0xC0},//
	{0x904C ,0x50},//
	{0x904D ,0x15},//
	{0x904E ,0x90},//
	{0x904F ,0xA5},//
	{0x9050 ,0xBA},//
	{0x9051 ,0x74},//
	{0x9052 ,0x4D},//
	{0x9053 ,0xF0},//
	{0x9054 ,0xA3},//
	{0x9055 ,0x74},//
	{0x9056 ,0xCD},//
	{0x9057 ,0xF0},//
	{0x9058 ,0xA3},//
	{0x9059 ,0x74},//
	{0x905A ,0x40},//
	{0x905B ,0xF0},//
	{0x905C ,0xA3},//
	{0x905D ,0x74},//
	{0x905E ,0x8D},//
	{0x905F ,0xF0},//
	{0x9060 ,0x02},//
	{0x9061 ,0x51},//
	{0x9062 ,0x1F},//
	{0x9063 ,0xEF},//
	{0x9064 ,0xC3},//
	{0x9065 ,0x94},//
	{0x9066 ,0xE0},//
	{0x9067 ,0x50},//
	{0x9068 ,0x15},//
	{0x9069 ,0x90},//
	{0x906A ,0xA5},//
	{0x906B ,0xBA},//
	{0x906C ,0x74},//
	{0x906D ,0x4D},//
	{0x906E ,0xF0},//
	{0x906F ,0xA3},//
	{0x9070 ,0x74},//
	{0x9071 ,0xF3},//
	{0x9072 ,0xF0},//
	{0x9073 ,0xA3},//
	{0x9074 ,0x74},//
	{0x9075 ,0x40},//
	{0x9076 ,0xF0},//
	{0x9077 ,0xA3},//
	{0x9078 ,0x74},//
	{0x9079 ,0x88},//
	{0x907A ,0xF0},//
	{0x907B ,0x02},//
	{0x907C ,0x51},//
	{0x907D ,0x1F},//
	{0x907E ,0xEF},//
	{0x907F ,0xC3},//
	{0x9080 ,0x94},//
	{0x9081 ,0xF0},//
	{0x9082 ,0x90},//
	{0x9083 ,0xA5},//
	{0x9084 ,0xBA},//
	{0x9085 ,0x74},//
	{0x9086 ,0x4E},//
	{0x9087 ,0x50},//
	{0x9088 ,0x10},//
	{0x9089 ,0xF0},//
	{0x908A ,0xA3},//
	{0x908B ,0x74},//
	{0x908C ,0x16},//
	{0x908D ,0xF0},//
	{0x908E ,0xA3},//
	{0x908F ,0x74},//
	{0x9090 ,0x40},//
	{0x9091 ,0xF0},//
	{0x9092 ,0xA3},//
	{0x9093 ,0x74},//
	{0x9094 ,0x78},//
	{0x9095 ,0xF0},//
	{0x9096 ,0x02},//
	{0x9097 ,0x51},//
	{0x9098 ,0x1F},//
	{0x9099 ,0xF0},//
	{0x909A ,0xA3},//
	{0x909B ,0x74},//
	{0x909C ,0x3C},//
	{0x909D ,0xF0},//
	{0x909E ,0xA3},//
	{0x909F ,0x74},//
	{0x90A0 ,0x40},//
	{0x90A1 ,0xF0},//
	{0x90A2 ,0xA3},//
	{0x90A3 ,0x74},//
	{0x90A4 ,0x7E},//
	{0x90A5 ,0xF0},//
	{0x90A6 ,0x80},//
	{0x90A7 ,0x77},//
	{0x90A8 ,0x90},//
	{0x90A9 ,0xA5},//
	{0x90AA ,0xB9},//
	{0x90AB ,0xE0},//
	{0x90AC ,0xFF},//
	{0x90AD ,0xC3},//
	{0x90AE ,0x94},//
	{0x90AF ,0x80},//
	{0x90B0 ,0x50},//
	{0x90B1 ,0x12},//
	{0x90B2 ,0xA3},//
	{0x90B3 ,0x74},//
	{0x90B4 ,0x4B},//
	{0x90B5 ,0xF0},//
	{0x90B6 ,0xA3},//
	{0x90B7 ,0x74},//
	{0x90B8 ,0xAA},//
	{0x90B9 ,0xF0},//
	{0x90BA ,0xA3},//
	{0x90BB ,0x74},//
	{0x90BC ,0x40},//
	{0x90BD ,0xF0},//
	{0x90BE ,0xA3},//
	{0x90BF ,0x74},//
	{0x90C0 ,0x9A},//
	{0x90C1 ,0xF0},//
	{0x90C2 ,0x80},//
	{0x90C3 ,0x5B},//
	{0x90C4 ,0xEF},//
	{0x90C5 ,0xC3},//
	{0x90C6 ,0x94},//
	{0x90C7 ,0xC0},//
	{0x90C8 ,0x50},//
	{0x90C9 ,0x14},//
	{0x90CA ,0x90},//
	{0x90CB ,0xA5},//
	{0x90CC ,0xBA},//
	{0x90CD ,0x74},//
	{0x90CE ,0x4B},//
	{0x90CF ,0xF0},//
	{0x90D0 ,0xA3},//
	{0x90D1 ,0x74},//
	{0x90D2 ,0xC4},//
	{0x90D3 ,0xF0},//
	{0x90D4 ,0xA3},//
	{0x90D5 ,0x74},//
	{0x90D6 ,0x40},//
	{0x90D7 ,0xF0},//
	{0x90D8 ,0xA3},//
	{0x90D9 ,0x74},//
	{0x90DA ,0x9C},//
	{0x90DB ,0xF0},//
	{0x90DC ,0x80},//
	{0x90DD ,0x41},//
	{0x90DE ,0xEF},//
	{0x90DF ,0xC3},//
	{0x90E0 ,0x94},//
	{0x90E1 ,0xE0},//
	{0x90E2 ,0x50},//
	{0x90E3 ,0x14},//
	{0x90E4 ,0x90},//
	{0x90E5 ,0xA5},//
	{0x90E6 ,0xBA},//
	{0x90E7 ,0x74},//
	{0x90E8 ,0x4B},//
	{0x90E9 ,0xF0},//
	{0x90EA ,0xA3},//
	{0x90EB ,0x74},//
	{0x90EC ,0xEB},//
	{0x90ED ,0xF0},//
	{0x90EE ,0xA3},//
	{0x90EF ,0x74},//
	{0x90F0 ,0x40},//
	{0x90F1 ,0xF0},//
	{0x90F2 ,0xA3},//
	{0x90F3 ,0x74},//
	{0x90F4 ,0x8D},//
	{0x90F5 ,0xF0},//
	{0x90F6 ,0x80},//
	{0x90F7 ,0x27},//
	{0x90F8 ,0xEF},//
	{0x90F9 ,0xC3},//
	{0x90FA ,0x94},//
	{0x90FB ,0xF0},//
	{0x90FC ,0x90},//
	{0x90FD ,0xA5},//
	{0x90FE ,0xBA},//
	{0x90FF ,0x74},//
	{0x9100 ,0x4C},//
	{0x9101 ,0x50},//
	{0x9102 ,0x0F},//
	{0x9103 ,0xF0},//
	{0x9104 ,0xA3},//
	{0x9105 ,0x74},//
	{0x9106 ,0x0F},//
	{0x9107 ,0xF0},//
	{0x9108 ,0xA3},//
	{0x9109 ,0x74},//
	{0x910A ,0x40},//
	{0x910B ,0xF0},//
	{0x910C ,0xA3},//
	{0x910D ,0x74},//
	{0x910E ,0x8A},//
	{0x910F ,0xF0},//
	{0x9110 ,0x80},//
	{0x9111 ,0x0D},//
	{0x9112 ,0xF0},//
	{0x9113 ,0xA3},//
	{0x9114 ,0x74},//
	{0x9115 ,0x1E},//
	{0x9116 ,0xF0},//
	{0x9117 ,0xA3},//
	{0x9118 ,0x74},//
	{0x9119 ,0x40},//
	{0x911A ,0xF0},//
	{0x911B ,0xA3},//
	{0x911C ,0x74},//
	{0x911D ,0xA4},//
	{0x911E ,0xF0},//
	{0x911F ,0x90},//
	{0x9120 ,0xA5},//
	{0x9121 ,0xB5},//
	{0x9122 ,0x02},//
	{0x9123 ,0x11},//
	{0x9124 ,0xA0},//
	{0x9125 ,0x02},//
	{0x9126 ,0x12},//
	{0x9127 ,0x4F},//
	{0x9128 ,0x74},//
	{0x9129 ,0x00},//
	{0x912A ,0xF0},//
	{0x912B ,0x90},//
	{0x912C ,0xA6},//
	{0x912D ,0x7D},//
	{0x912E ,0x74},//
	{0x912F ,0x02},//
	{0x9130 ,0xF0},//
	{0x9131 ,0x90},//
	{0x9132 ,0xA6},//
	{0x9133 ,0x7F},//
	{0x9134 ,0xF0},//
	{0x9135 ,0x90},//
	{0x9136 ,0x31},//
	{0x9137 ,0x27},//
	{0x9138 ,0x74},//
	{0x9139 ,0x32},//
	{0x913A ,0xF0},//
	{0x913B ,0x02},//
	{0x913C ,0x0B},//
	{0x913D ,0x58},//
	{0x913E ,0xE0},//
	{0x913F ,0xFE},//
	{0x9140 ,0xA3},//
	{0x9141 ,0xE0},//
	{0x9142 ,0xFF},//
	{0x9143 ,0x90},//
	{0x9144 ,0xA6},//
	{0x9145 ,0x24},//
	{0x9146 ,0xEE},//
	{0x9147 ,0xF0},//
	{0x9148 ,0xA3},//
	{0x9149 ,0xEF},//
	{0x914A ,0xF0},//
	{0x914B ,0xC3},//
	{0x914C ,0xEE},//
	{0x914D ,0x64},//
	{0x914E ,0x80},//
	{0x914F ,0x94},//
	{0x9150 ,0x80},//
	{0x9151 ,0x50},//
	{0x9152 ,0x0F},//
	{0x9153 ,0x90},//
	{0x9154 ,0xA5},//
	{0x9155 ,0xCA},//
	{0x9156 ,0xE0},//
	{0x9157 ,0xFF},//
	{0x9158 ,0xA3},//
	{0x9159 ,0xE0},//
	{0x915A ,0x90},//
	{0x915B ,0xA6},//
	{0x915C ,0x24},//
	{0x915D ,0xCF},//
	{0x915E ,0xF0},//
	{0x915F ,0xA3},//
	{0x9160 ,0xEF},//
	{0x9161 ,0xF0},//
	{0x9162 ,0x90},//
	{0x9163 ,0xA5},//
	{0x9164 ,0xCE},//
	{0x9165 ,0xE0},//
	{0x9166 ,0xFA},//
	{0x9167 ,0xA3},//
	{0x9168 ,0xE0},//
	{0x9169 ,0xFB},//
	{0x916A ,0xF5},//
	{0x916B ,0x82},//
	{0x916C ,0x8A},//
	{0x916D ,0x83},//
	{0x916E ,0xA3},//
	{0x916F ,0xA3},//
	{0x9170 ,0xE0},//
	{0x9171 ,0xFE},//
	{0x9172 ,0xA3},//
	{0x9173 ,0xE0},//
	{0x9174 ,0xFF},//
	{0x9175 ,0x90},//
	{0x9176 ,0xA6},//
	{0x9177 ,0x1E},//
	{0x9178 ,0xEE},//
	{0x9179 ,0xF0},//
	{0x917A ,0xA3},//
	{0x917B ,0xEF},//
	{0x917C ,0xF0},//
	{0x917D ,0x4E},//
	{0x917E ,0x70},//
	{0x917F ,0x18},//
	{0x9180 ,0x90},//
	{0x9181 ,0xA6},//
	{0x9182 ,0x24},//
	{0x9183 ,0xE0},//
	{0x9184 ,0xFE},//
	{0x9185 ,0xA3},//
	{0x9186 ,0xE0},//
	{0x9187 ,0xFF},//
	{0x9188 ,0x90},//
	{0x9189 ,0xA6},//
	{0x918A ,0x24},//
	{0x918B ,0xEE},//
	{0x918C ,0x00},//
	{0x918D ,0xA3},//
	{0x918E ,0xEF},//
	{0x918F ,0x00},//
	{0x9190 ,0x90},//
	{0x9191 ,0xA6},//
	{0x9192 ,0x1E},//
	{0x9193 ,0xEE},//
	{0x9194 ,0xF0},//
	{0x9195 ,0xA3},//
	{0x9196 ,0xEF},//
	{0x9197 ,0xF0},//
	{0x9198 ,0x90},//
	{0x9199 ,0xA6},//
	{0x919A ,0x1E},//
	{0x919B ,0xE0},//
	{0x919C ,0xFC},//
	{0x919D ,0xA3},//
	{0x919E ,0xE0},//
	{0x919F ,0xFD},//
	{0x91A0 ,0xAE},//
	{0x91A1 ,0x04},//
	{0x91A2 ,0x78},//
	{0x91A3 ,0x03},//
	{0x91A4 ,0xCE},//
	{0x91A5 ,0xC3},//
	{0x91A6 ,0x13},//
	{0x91A7 ,0xCE},//
	{0x91A8 ,0x13},//
	{0x91A9 ,0xD8},//
	{0x91AA ,0xF9},//
	{0x91AB ,0xFF},//
	{0x91AC ,0xC3},//
	{0x91AD ,0xED},//
	{0x91AE ,0x9F},//
	{0x91AF ,0xFD},//
	{0x91B0 ,0xEC},//
	{0x91B1 ,0x9E},//
	{0x91B2 ,0xFC},//
	{0x91B3 ,0x90},//
	{0x91B4 ,0xA6},//
	{0x91B5 ,0x24},//
	{0x91B6 ,0xE0},//
	{0x91B7 ,0xFE},//
	{0x91B8 ,0xA3},//
	{0x91B9 ,0xE0},//
	{0x91BA ,0x78},//
	{0x91BB ,0x03},//
	{0x91BC ,0xCE},//
	{0x91BD ,0xC3},//
	{0x91BE ,0x13},//
	{0x91BF ,0xCE},//
	{0x91C0 ,0x13},//
	{0x91C1 ,0xD8},//
	{0x91C2 ,0xF9},//
	{0x91C3 ,0x2D},//
	{0x91C4 ,0xFF},//
	{0x91C5 ,0xEC},//
	{0x91C6 ,0x3E},//
	{0x91C7 ,0xFE},//
	{0x91C8 ,0xE4},//
	{0x91C9 ,0xFC},//
	{0x91CA ,0xFD},//
	{0x91CB ,0x8B},//
	{0x91CC ,0x82},//
	{0x91CD ,0x8A},//
	{0x91CE ,0x83},//
	{0x91CF ,0x02},//
	{0x91D0 ,0x12},//
	{0x91D1 ,0x96},//
	{0x91d6 ,0x74},//
	{0x91d7 ,0x00},//
	{0x91d8 ,0x90},//
	{0x91d9 ,0x42},//
	{0x91dA ,0x04},//
	{0x91dB ,0xF0},//
	{0x91dC ,0xA3},//
	{0x91dD ,0xF0},//
	{0x91dE ,0xA3},//
	{0x91dF ,0xA3},//
	{0x91e0 ,0xA3},//
	{0x91e1 ,0xF0},//
	{0x91e2 ,0xA3},//
	{0x91e3 ,0xF0},//
	{0x91e4 ,0xA3},//
	{0x91e5 ,0xA3},//
	{0x91e6 ,0xA3},//
	{0x91e7 ,0xF0},//
	{0x91e8 ,0xA3},//
	{0x91e9 ,0xF0},//
	{0x91eA ,0xA3},//
	{0x91eB ,0xA3},//
	{0x91eC ,0xA3},//
	{0x91eD ,0xF0},//
	{0x91eE ,0xA3},//
	{0x91eF ,0xF0},//
	{0x91f0 ,0x90},//
	{0x91f1 ,0x42},//
	{0x91f2 ,0x00},//
	{0x91f3 ,0x74},//
	{0x91f4 ,0x0D},//
	{0x91f5 ,0xF0},//
	{0x91f6 ,0x22},//
	{0x91f7 ,0x90},//
	{0x91f8 ,0xA3},//
	{0x91f9 ,0xE5},//
	{0x91fa ,0xE0},//
	{0x91fb ,0xB4},//
	{0x91fc ,0x03},//
	{0x91fd ,0x0F},//
	{0x91fe ,0xA3},//
	{0x91ff ,0xE0},//
	{0x9200 ,0xB4},//
	{0x9201 ,0x02},//
	{0x9202 ,0x0A},//
	{0x9203 ,0x90},//
	{0x9204 ,0x85},//
	{0x9205 ,0x2c},//
	{0x9206 ,0x74},//
	{0x9207 ,0x03},//
	{0x9208 ,0xf0},//
	{0x9209 ,0x90},//
	{0x920a ,0x85},//
	{0x920b ,0x32},//
	{0x920c ,0xf0},//
	{0x920d ,0x78},//
	{0x920e ,0x11},//
	{0x920f ,0x76},//
	{0x9210 ,0x01},//
	{0x9211 ,0x22},//
	{0x9213 ,0x90},//
	{0x9214 ,0x31},//
	{0x9215 ,0x7D},//
	{0x9216 ,0xE0},//
	{0x9217 ,0xFF},//
	{0x9218 ,0x90},//
	{0x9219 ,0xA6},//
	{0x921A ,0x20},//
	{0x921B ,0xE0},//
	{0x921C ,0x6F},//
	{0x921D ,0x60},//
	{0x921E ,0x21},//
	{0x921F ,0x90},//
	{0x9220 ,0x31},//
	{0x9221 ,0x7D},//
	{0x9222 ,0xE0},//
	{0x9223 ,0x90},//
	{0x9224 ,0xA6},//
	{0x9225 ,0x20},//
	{0x9226 ,0xF0},//
	{0x9227 ,0xE4},//
	{0x9228 ,0x90},//
	{0x9229 ,0x42},//
	{0x922A ,0x04},//
	{0x922B ,0xF0},//
	{0x922C ,0xA3},//
	{0x922D ,0xF0},//
	{0x922E ,0x90},//
	{0x922F ,0x42},//
	{0x9230 ,0x08},//
	{0x9231 ,0xF0},//
	{0x9232 ,0xA3},//
	{0x9233 ,0xF0},//
	{0x9234 ,0x90},//
	{0x9235 ,0x42},//
	{0x9236 ,0x0C},//
	{0x9237 ,0xF0},//
	{0x9238 ,0xA3},//
	{0x9239 ,0xF0},//
	{0x923A ,0x90},//
	{0x923B ,0x42},//
	{0x923C ,0x10},//
	{0x923D ,0xF0},//
	{0x923E ,0xA3},//
	{0x923F ,0xF0},//
	{0x9240 ,0x22},//
	{0x9241 ,0x90},//
	{0x9242 ,0x31},//
	{0x9243 ,0x45},//
	{0x9244 ,0xE0},//
	{0x9245 ,0xFF},//
	{0x9246 ,0x90},//
	{0x9247 ,0x31},//
	{0x9248 ,0x7D},//
	{0x9249 ,0xE0},//
	{0x924A ,0x6F},//
	{0x924B ,0x60},//
	{0x924C ,0x07},//
	{0x924D ,0x90},//
	{0x924E ,0x42},//
	{0x924F ,0x00},//
	{0x9250 ,0xE0},//
	{0x9251 ,0x44},//
	{0x9252 ,0x08},//
	{0x9253 ,0xF0},//
	{0x9254 ,0x22},//
	{0x8504 ,0x39},//
	{0x8505 ,0x17},//
	{0x8506 ,0x00},//
	{0x8507 ,0xF0},//
	{0x8508 ,0x03},//
	{0x850a ,0x13},//
	{0x850b ,0x19},//
	{0x850c ,0x00},//
	{0x850d ,0x00},//
	{0x850e ,0x02},//
	{0x8510 ,0x43},//
	{0x8511 ,0x8B},//
	{0x8512 ,0x00},//
	{0x8513 ,0x08},//
	{0x8514 ,0x02},//
	{0x8516 ,0x12},//
	{0x8517 ,0x36},//
	{0x8518 ,0x00},//
	{0x8519 ,0x11},//
	{0x851A ,0x02},//
	{0x851C ,0x10},//
	{0x851D ,0x01},//
	{0x851E ,0x00},//
	{0x851F ,0x1D},//
	{0x8520 ,0x02},//
	{0x8522 ,0x12},//
	{0x8523 ,0x40},//
	{0x8524 ,0x01},//
	{0x8525 ,0x25},//
	{0x8526 ,0x02},//
	{0x8528 ,0x14},//
	{0x8529 ,0x60},//
	{0x852A ,0x00},//
	{0x852B ,0xE4},//
	{0x852C ,0x00},//
	{0x852E ,0x15},//
	{0x852F ,0xA0},//
	{0x8530 ,0x00},//
	{0x8531 ,0xE2},//
	{0x8532 ,0x00},//
	{0x8534 ,0x0B},//
	{0x8535 ,0x55},//
	{0x8536 ,0x01},//
	{0x8537 ,0x28},//
	{0x8538 ,0x02},//
	{0x853A ,0x12},//
	{0x853B ,0x80},//
	{0x853C ,0x01},//
	{0x853D ,0x3E},//
	{0x853E ,0x02},//
	{0x8540 ,0x3E},//
	{0x8541 ,0x29},//
	{0x8542 ,0x01},//
	{0x8543 ,0xD6},//
	{0x8544 ,0x02},//
	{0x8546 ,0x43},//
	{0x8547 ,0x87},//
	{0x8548 ,0x01},//
	{0x8549 ,0xF7},//
	{0x854A ,0x02},//
	{0x854c ,0x45},//
	{0x854d ,0x08},//
	{0x854e ,0x02},//
	{0x854f ,0x13},//
	{0x8550 ,0x02},//
	{0x8552 ,0x4A},//
	{0x8553 ,0x87},//
	{0x8554 ,0x02},//
	{0x8555 ,0x41},//
	{0x8556 ,0x02},//
	{0x8500 ,0x01},//			;Enable Ram and disable Write;
	{0xffff ,0x00},//			;MCU Reset;
	{0xcdcd ,200},
	{0x0101 ,0x03},//; Rotate
	{0x0112 ,0x0A},//
	{0x0113 ,0x0A},//
	{0x0111 ,0x02},//
	{0x0304 ,0x00},//
	{0x0305 ,0x02},//
	{0x0306 ,0x00},//
	{0x0307 ,0x6e/*4b*/},//
	{0x0302 ,0x00},//
	{0x0303 ,0x05},//
	{0x0300 ,0x00},//
	{0x0301 ,0x01},//
	{0xA649 ,0x00},//
	{0x0200 ,0x02},//
	{0x0201 ,0xB0},//
	{0x0202 ,0x01},//
	{0x0203 ,0x90},//
	{0x0204 ,0x00},//
	{0x0205 ,0x60},//
	{0x3020 ,0x0F},//
	{0x801A ,0x05},//
	{0x8023 ,0x11},//
	{0x8027 ,0x11},//
	{0x8011 ,0x06},//
	{0x034C ,0x0C},//
	{0x034D ,0xE0},//
	{0x034E ,0x09},//
	{0x034F ,0xB0},//
	{0x5300 ,0x01},//
	{0x5318 ,0x0C},//
	{0x5319 ,0xE0},//
	{0x531C ,0x09},//
	{0x531D ,0xB0},//
	{0x5320 ,0x0C},//
	{0x5321 ,0xE0},//
	{0x5324 ,0x09},//
	{0x5325 ,0xB0},//
	{0x0344 ,0x00},//
	{0x0345 ,0x00},//
	{0x0348 ,0x0C},//
	{0x0349 ,0xDF},//
	{0x0346 ,0x00},//
	{0x0347 ,0x00},//
	{0x034A ,0x09},//
	{0x034B ,0xAF},//
	{0x0380 ,0x00},//
	{0x0381 ,0x01},//
	{0x0382 ,0x00},//
	{0x0383 ,0x01},//
	{0x0384 ,0x00},//
	{0x0385 ,0x01},//
	{0x0386 ,0x00},//
	{0x0387 ,0x01},//
	{0xA608 ,0x04},//; Load Bruce Data from OTP
	{0xA607 ,0x01},//
	{0xA649,0x00},////vtiming mode = binning ct
	{0x0382,0x00},//
	{0x0383,0x01},////x_odd_inc  
	{0x0386,0x00},//
	{0x0387,0x01},////y_odd_inc
	{0x0340,0x09},//
	{0x0341,0xEC},//
	{0x0344,0x00},////x start size
	{0x0345,0x00},//
	{0x0346,0x00},////y start size
	{0x0347,0x00},//
	{0x0348,0x0C},//
	{0x0349,0xDF},////x end size
	{0x034a,0x09},//
	{0x034B,0xAF},////y end size
	{0x034C,0x0C},//
	{0x034D,0xC0},////x output size
	{0x034E,0x09},//
	{0x034F,0x90},////y output size
	{0x0100,0x01},//

};


//for video
static struct regval_list sensor_1080p_regs[] = { //1080: 1920*1080@30fps

	{0x0103,0x01 },//
	{0xffff,0x01 },//	 ;MCU bypass;
	{0x8500,0x03 },//	 ;Enable Ram and enable Write;
	{0x9000,0xF0 },//
	{0x9001,0x90 },//
	{0x9002,0x52 },//
	{0x9003,0x00 },//
	{0x9004,0xF0 },//
	{0x9005,0x02 },//
	{0x9006,0x13 },//
	{0x9007,0x1A },//
	{0x9008,0x90 },//
	{0x9009,0x30 },//
	{0x900A,0x6c },//
	{0x900B,0xE0 },//
	{0x900C,0x90 },//
	{0x900D,0x00 },//
	{0x900E,0x02 },//
	{0x900F,0xF0 },//
	{0x9010,0x22 },//
	{0x9011,0x24 },//
	{0x9012,0xFE },//
	{0x9013,0xF0 },//
	{0x9014,0x90 },//
	{0x9015,0xA5 },//
	{0x9016,0xB5 },//
	{0x9017,0xE0 },//
	{0x9018,0x34 },//
	{0x9019,0xFF },//
	{0x901A,0x02 },//
	{0x901B,0x12 },//
	{0x901C,0x3F },//
	{0x901D,0x90 },//
	{0x901E,0xA6 },//
	{0x901F,0x49 },//
	{0x9020,0xE0 },//
	{0x9021,0xFF },//
	{0x9022,0x64 },//
	{0x9023,0x01 },//
	{0x9024,0x60 },//
	{0x9025,0x05 },//
	{0x9026,0xEF },//
	{0x9027,0x64 },//
	{0x9028,0x04 },//
	{0x9029,0x70 },//
	{0x902A,0x7D },//
	{0x902B,0x90 },//
	{0x902C,0xA5 },//
	{0x902D,0xB9 },//
	{0x902E,0xE0 },//
	{0x902F,0xFF },//
	{0x9030,0xC3 },//
	{0x9031,0x94 },//
	{0x9032,0x80 },//
	{0x9033,0x50 },//
	{0x9034,0x13 },//
	{0x9035,0xA3 },//
	{0x9036,0x74 },//
	{0x9037,0x4D },//
	{0x9038,0xF0 },//
	{0x9039,0xA3 },//
	{0x903A,0x74 },//
	{0x903B,0xB3 },//
	{0x903C,0xF0 },//
	{0x903D,0xA3 },//
	{0x903E,0x74 },//
	{0x903F,0x40 },//
	{0x9040,0xF0 },//
	{0x9041,0xA3 },//
	{0x9042,0x74 },//
	{0x9043,0x9B },//
	{0x9044,0xF0 },//
	{0x9045,0x02 },//
	{0x9046,0x51 },//
	{0x9047,0x1F },//
	{0x9048,0xEF },//
	{0x9049,0xC3 },//
	{0x904A,0x94 },//
	{0x904B,0xC0 },//
	{0x904C,0x50 },//
	{0x904D,0x15 },//
	{0x904E,0x90 },//
	{0x904F,0xA5 },//
	{0x9050,0xBA },//
	{0x9051,0x74 },//
	{0x9052,0x4D },//
	{0x9053,0xF0 },//
	{0x9054,0xA3 },//
	{0x9055,0x74 },//
	{0x9056,0xCD },//
	{0x9057,0xF0 },//
	{0x9058,0xA3 },//
	{0x9059,0x74 },//
	{0x905A,0x40 },//
	{0x905B,0xF0 },//
	{0x905C,0xA3 },//
	{0x905D,0x74 },//
	{0x905E,0x8D },//
	{0x905F,0xF0 },//
	{0x9060,0x02 },//
	{0x9061,0x51 },//
	{0x9062,0x1F },//
	{0x9063,0xEF },//
	{0x9064,0xC3 },//
	{0x9065,0x94 },//
	{0x9066,0xE0 },//
	{0x9067,0x50 },//
	{0x9068,0x15 },//
	{0x9069,0x90 },//
	{0x906A,0xA5 },//
	{0x906B,0xBA },//
	{0x906C,0x74 },//
	{0x906D,0x4D },//
	{0x906E,0xF0 },//
	{0x906F,0xA3 },//
	{0x9070,0x74 },//
	{0x9071,0xF3 },//
	{0x9072,0xF0 },//
	{0x9073,0xA3 },//
	{0x9074,0x74 },//
	{0x9075,0x40 },//
	{0x9076,0xF0 },//
	{0x9077,0xA3 },//
	{0x9078,0x74 },//
	{0x9079,0x88 },//
	{0x907A,0xF0 },//
	{0x907B,0x02 },//
	{0x907C,0x51 },//
	{0x907D,0x1F },//
	{0x907E,0xEF },//
	{0x907F,0xC3 },//
	{0x9080,0x94 },//
	{0x9081,0xF0 },//
	{0x9082,0x90 },//
	{0x9083,0xA5 },//
	{0x9084,0xBA },//
	{0x9085,0x74 },//
	{0x9086,0x4E },//
	{0x9087,0x50 },//
	{0x9088,0x10 },//
	{0x9089,0xF0 },//
	{0x908A,0xA3 },//
	{0x908B,0x74 },//
	{0x908C,0x16 },//
	{0x908D,0xF0 },//
	{0x908E,0xA3 },//
	{0x908F,0x74 },//
	{0x9090,0x40 },//
	{0x9091,0xF0 },//
	{0x9092,0xA3 },//
	{0x9093,0x74 },//
	{0x9094,0x78 },//
	{0x9095,0xF0 },//
	{0x9096,0x02 },//
	{0x9097,0x51 },//
	{0x9098,0x1F },//
	{0x9099,0xF0 },//
	{0x909A,0xA3 },//
	{0x909B,0x74 },//
	{0x909C,0x3C },//
	{0x909D,0xF0 },//
	{0x909E,0xA3 },//
	{0x909F,0x74 },//
	{0x90A0,0x40 },//
	{0x90A1,0xF0 },//
	{0x90A2,0xA3 },//
	{0x90A3,0x74 },//
	{0x90A4,0x7E },//
	{0x90A5,0xF0 },//
	{0x90A6,0x80 },//
	{0x90A7,0x77 },//
	{0x90A8,0x90 },//
	{0x90A9,0xA5 },//
	{0x90AA,0xB9 },//
	{0x90AB,0xE0 },//
	{0x90AC,0xFF },//
	{0x90AD,0xC3 },//
	{0x90AE,0x94 },//
	{0x90AF,0x80 },//
	{0x90B0,0x50 },//
	{0x90B1,0x12 },//
	{0x90B2,0xA3 },//
	{0x90B3,0x74 },//
	{0x90B4,0x4B },//
	{0x90B5,0xF0 },//
	{0x90B6,0xA3 },//
	{0x90B7,0x74 },//
	{0x90B8,0xAA },//
	{0x90B9,0xF0 },//
	{0x90BA,0xA3 },//
	{0x90BB,0x74 },//
	{0x90BC,0x40 },//
	{0x90BD,0xF0 },//
	{0x90BE,0xA3 },//
	{0x90BF,0x74 },//
	{0x90C0,0x9A },//
	{0x90C1,0xF0 },//
	{0x90C2,0x80 },//
	{0x90C3,0x5B },//
	{0x90C4,0xEF },//
	{0x90C5,0xC3 },//
	{0x90C6,0x94 },//
	{0x90C7,0xC0 },//
	{0x90C8,0x50 },//
	{0x90C9,0x14 },//
	{0x90CA,0x90 },//
	{0x90CB,0xA5 },//
	{0x90CC,0xBA },//
	{0x90CD,0x74 },//
	{0x90CE,0x4B },//
	{0x90CF,0xF0 },//
	{0x90D0,0xA3 },//
	{0x90D1,0x74 },//
	{0x90D2,0xC4 },//
	{0x90D3,0xF0 },//
	{0x90D4,0xA3 },//
	{0x90D5,0x74 },//
	{0x90D6,0x40 },//
	{0x90D7,0xF0 },//
	{0x90D8,0xA3 },//
	{0x90D9,0x74 },//
	{0x90DA,0x9C },//
	{0x90DB,0xF0 },//
	{0x90DC,0x80 },//
	{0x90DD,0x41 },//
	{0x90DE,0xEF },//
	{0x90DF,0xC3 },//
	{0x90E0,0x94 },//
	{0x90E1,0xE0 },//
	{0x90E2,0x50 },//
	{0x90E3,0x14 },//
	{0x90E4,0x90 },//
	{0x90E5,0xA5 },//
	{0x90E6,0xBA },//
	{0x90E7,0x74 },//
	{0x90E8,0x4B },//
	{0x90E9,0xF0 },//
	{0x90EA,0xA3 },//
	{0x90EB,0x74 },//
	{0x90EC,0xEB },//
	{0x90ED,0xF0 },//
	{0x90EE,0xA3 },//
	{0x90EF,0x74 },//
	{0x90F0,0x40 },//
	{0x90F1,0xF0 },//
	{0x90F2,0xA3 },//
	{0x90F3,0x74 },//
	{0x90F4,0x8D },//
	{0x90F5,0xF0 },//
	{0x90F6,0x80 },//
	{0x90F7,0x27 },//
	{0x90F8,0xEF },//
	{0x90F9,0xC3 },//
	{0x90FA,0x94 },//
	{0x90FB,0xF0 },//
	{0x90FC,0x90 },//
	{0x90FD,0xA5 },//
	{0x90FE,0xBA },//
	{0x90FF,0x74 },//
	{0x9100,0x4C },//
	{0x9101,0x50 },//
	{0x9102,0x0F },//
	{0x9103,0xF0 },//
	{0x9104,0xA3 },//
	{0x9105,0x74 },//
	{0x9106,0x0F },//
	{0x9107,0xF0 },//
	{0x9108,0xA3 },//
	{0x9109,0x74 },//
	{0x910A,0x40 },//
	{0x910B,0xF0 },//
	{0x910C,0xA3 },//
	{0x910D,0x74 },//
	{0x910E,0x8A },//
	{0x910F,0xF0 },//
	{0x9110,0x80 },//
	{0x9111,0x0D },//
	{0x9112,0xF0 },//
	{0x9113,0xA3 },//
	{0x9114,0x74 },//
	{0x9115,0x1E },//
	{0x9116,0xF0 },//
	{0x9117,0xA3 },//
	{0x9118,0x74 },//
	{0x9119,0x40 },//
	{0x911A,0xF0 },//
	{0x911B,0xA3 },//
	{0x911C,0x74 },//
	{0x911D,0xA4 },//
	{0x911E,0xF0 },//
	{0x911F,0x90 },//
	{0x9120,0xA5 },//
	{0x9121,0xB5 },//
	{0x9122,0x02 },//
	{0x9123,0x11 },//
	{0x9124,0xA0 },//
	{0x9125,0x02 },//
	{0x9126,0x12 },//
	{0x9127,0x4F },//
	{0x9128,0x74 },//
	{0x9129,0x00 },//
	{0x912A,0xF0 },//
	{0x912B,0x90 },//
	{0x912C,0xA6 },//
	{0x912D,0x7D },//
	{0x912E,0x74 },//
	{0x912F,0x02 },//
	{0x9130,0xF0 },//
	{0x9131,0x90 },//
	{0x9132,0xA6 },//
	{0x9133,0x7F },//
	{0x9134,0xF0 },//
	{0x9135,0x90 },//
	{0x9136,0x31 },//
	{0x9137,0x27 },//
	{0x9138,0x74 },//
	{0x9139,0x32 },//
	{0x913A,0xF0 },//
	{0x913B,0x02 },//
	{0x913C,0x0B },//
	{0x913D,0x58 },//
	{0x913E,0xE0 },//
	{0x913F,0xFE },//
	{0x9140,0xA3 },//
	{0x9141,0xE0 },//
	{0x9142,0xFF },//
	{0x9143,0x90 },//
	{0x9144,0xA6 },//
	{0x9145,0x24 },//
	{0x9146,0xEE },//
	{0x9147,0xF0 },//
	{0x9148,0xA3 },//
	{0x9149,0xEF },//
	{0x914A,0xF0 },//
	{0x914B,0xC3 },//
	{0x914C,0xEE },//
	{0x914D,0x64 },//
	{0x914E,0x80 },//
	{0x914F,0x94 },//
	{0x9150,0x80 },//
	{0x9151,0x50 },//
	{0x9152,0x0F },//
	{0x9153,0x90 },//
	{0x9154,0xA5 },//
	{0x9155,0xCA },//
	{0x9156,0xE0 },//
	{0x9157,0xFF },//
	{0x9158,0xA3 },//
	{0x9159,0xE0 },//
	{0x915A,0x90 },//
	{0x915B,0xA6 },//
	{0x915C,0x24 },//
	{0x915D,0xCF },//
	{0x915E,0xF0 },//
	{0x915F,0xA3 },//
	{0x9160,0xEF },//
	{0x9161,0xF0 },//
	{0x9162,0x90 },//
	{0x9163,0xA5 },//
	{0x9164,0xCE },//
	{0x9165,0xE0 },//
	{0x9166,0xFA },//
	{0x9167,0xA3 },//
	{0x9168,0xE0 },//
	{0x9169,0xFB },//
	{0x916A,0xF5 },//
	{0x916B,0x82 },//
	{0x916C,0x8A },//
	{0x916D,0x83 },//
	{0x916E,0xA3 },//
	{0x916F,0xA3 },//
	{0x9170,0xE0 },//
	{0x9171,0xFE },//
	{0x9172,0xA3 },//
	{0x9173,0xE0 },//
	{0x9174,0xFF },//
	{0x9175,0x90 },//
	{0x9176,0xA6 },//
	{0x9177,0x1E },//
	{0x9178,0xEE },//
	{0x9179,0xF0 },//
	{0x917A,0xA3 },//
	{0x917B,0xEF },//
	{0x917C,0xF0 },//
	{0x917D,0x4E },//
	{0x917E,0x70 },//
	{0x917F,0x18 },//
	{0x9180,0x90 },//
	{0x9181,0xA6 },//
	{0x9182,0x24 },//
	{0x9183,0xE0 },//
	{0x9184,0xFE },//
	{0x9185,0xA3 },//
	{0x9186,0xE0 },//
	{0x9187,0xFF },//
	{0x9188,0x90 },//
	{0x9189,0xA6 },//
	{0x918A,0x24 },//
	{0x918B,0xEE },//
	{0x918C,0x00 },//
	{0x918D,0xA3 },//
	{0x918E,0xEF },//
	{0x918F,0x00 },//
	{0x9190,0x90 },//
	{0x9191,0xA6 },//
	{0x9192,0x1E },//
	{0x9193,0xEE },//
	{0x9194,0xF0 },//
	{0x9195,0xA3 },//
	{0x9196,0xEF },//
	{0x9197,0xF0 },//
	{0x9198,0x90 },//
	{0x9199,0xA6 },//
	{0x919A,0x1E },//
	{0x919B,0xE0 },//
	{0x919C,0xFC },//
	{0x919D,0xA3 },//
	{0x919E,0xE0 },//
	{0x919F,0xFD },//
	{0x91A0,0xAE },//
	{0x91A1,0x04 },//
	{0x91A2,0x78 },//
	{0x91A3,0x03 },//
	{0x91A4,0xCE },//
	{0x91A5,0xC3 },//
	{0x91A6,0x13 },//
	{0x91A7,0xCE },//
	{0x91A8,0x13 },//
	{0x91A9,0xD8 },//
	{0x91AA,0xF9 },//
	{0x91AB,0xFF },//
	{0x91AC,0xC3 },//
	{0x91AD,0xED },//
	{0x91AE,0x9F },//
	{0x91AF,0xFD },//
	{0x91B0,0xEC },//
	{0x91B1,0x9E },//
	{0x91B2,0xFC },//
	{0x91B3,0x90 },//
	{0x91B4,0xA6 },//
	{0x91B5,0x24 },//
	{0x91B6,0xE0 },//
	{0x91B7,0xFE },//
	{0x91B8,0xA3 },//
	{0x91B9,0xE0 },//
	{0x91BA,0x78 },//
	{0x91BB,0x03 },//
	{0x91BC,0xCE },//
	{0x91BD,0xC3 },//
	{0x91BE,0x13 },//
	{0x91BF,0xCE },//
	{0x91C0,0x13 },//
	{0x91C1,0xD8 },//
	{0x91C2,0xF9 },//
	{0x91C3,0x2D },//
	{0x91C4,0xFF },//
	{0x91C5,0xEC },//
	{0x91C6,0x3E },//
	{0x91C7,0xFE },//
	{0x91C8,0xE4 },//
	{0x91C9,0xFC },//
	{0x91CA,0xFD },//
	{0x91CB,0x8B },//
	{0x91CC,0x82 },//
	{0x91CD,0x8A },//
	{0x91CE,0x83 },//
	{0x91CF,0x02 },//
	{0x91D0,0x12 },//
	{0x91D1,0x96 },//
	{0x91d6,0x74 },//
	{0x91d7,0x00 },//
	{0x91d8,0x90 },//
	{0x91d9,0x42 },//
	{0x91dA,0x04 },//
	{0x91dB,0xF0 },//
	{0x91dC,0xA3 },//
	{0x91dD,0xF0 },//
	{0x91dE,0xA3 },//
	{0x91dF,0xA3 },//
	{0x91e0,0xA3 },//
	{0x91e1,0xF0 },//
	{0x91e2,0xA3 },//
	{0x91e3,0xF0 },//
	{0x91e4,0xA3 },//
	{0x91e5,0xA3 },//
	{0x91e6,0xA3 },//
	{0x91e7,0xF0 },//
	{0x91e8,0xA3 },//
	{0x91e9,0xF0 },//
	{0x91eA,0xA3 },//
	{0x91eB,0xA3 },//
	{0x91eC,0xA3 },//
	{0x91eD,0xF0 },//
	{0x91eE,0xA3 },//
	{0x91eF,0xF0 },//
	{0x91f0,0x90 },//
	{0x91f1,0x42 },//
	{0x91f2,0x00 },//
	{0x91f3,0x74 },//
	{0x91f4,0x0D },//
	{0x91f5,0xF0 },//
	{0x91f6,0x22 },//
	{0x91f7,0x90 },//
	{0x91f8,0xA3 },//
	{0x91f9,0xE5 },//
	{0x91fa,0xE0 },//
	{0x91fb,0xB4 },//
	{0x91fc,0x03 },//
	{0x91fd,0x0F },//
	{0x91fe,0xA3 },//
	{0x91ff,0xE0 },//
	{0x9200,0xB4 },//
	{0x9201,0x02 },//
	{0x9202,0x0A },//
	{0x9203,0x90 },//
	{0x9204,0x85 },//
	{0x9205,0x2c },//
	{0x9206,0x74 },//
	{0x9207,0x03 },//
	{0x9208,0xf0 },//
	{0x9209,0x90 },//
	{0x920a,0x85 },//
	{0x920b,0x32 },//
	{0x920c,0xf0 },//
	{0x920d,0x78 },//
	{0x920e,0x11 },//
	{0x920f,0x76 },//
	{0x9210,0x01 },//
	{0x9211,0x22 },//
	{0x9213,0x90 },//
	{0x9214,0x31 },//
	{0x9215,0x7D },//
	{0x9216,0xE0 },//
	{0x9217,0xFF },//
	{0x9218,0x90 },//
	{0x9219,0xA6 },//
	{0x921A,0x20 },//
	{0x921B,0xE0 },//
	{0x921C,0x6F },//
	{0x921D,0x60 },//
	{0x921E,0x21 },//
	{0x921F,0x90 },//
	{0x9220,0x31 },//
	{0x9221,0x7D },//
	{0x9222,0xE0 },//
	{0x9223,0x90 },//
	{0x9224,0xA6 },//
	{0x9225,0x20 },//
	{0x9226,0xF0 },//
	{0x9227,0xE4 },//
	{0x9228,0x90 },//
	{0x9229,0x42 },//
	{0x922A,0x04 },//
	{0x922B,0xF0 },//
	{0x922C,0xA3 },//
	{0x922D,0xF0 },//
	{0x922E,0x90 },//
	{0x922F,0x42 },//
	{0x9230,0x08 },//
	{0x9231,0xF0 },//
	{0x9232,0xA3 },//
	{0x9233,0xF0 },//
	{0x9234,0x90 },//
	{0x9235,0x42 },//
	{0x9236,0x0C },//
	{0x9237,0xF0 },//
	{0x9238,0xA3 },//
	{0x9239,0xF0 },//
	{0x923A,0x90 },//
	{0x923B,0x42 },//
	{0x923C,0x10 },//
	{0x923D,0xF0 },//
	{0x923E,0xA3 },//
	{0x923F,0xF0 },//
	{0x9240,0x22 },//
	{0x9241,0x90 },//
	{0x9242,0x31 },//
	{0x9243,0x45 },//
	{0x9244,0xE0 },//
	{0x9245,0xFF },//
	{0x9246,0x90 },//
	{0x9247,0x31 },//
	{0x9248,0x7D },//
	{0x9249,0xE0 },//
	{0x924A,0x6F },//
	{0x924B,0x60 },//
	{0x924C,0x07 },//
	{0x924D,0x90 },//
	{0x924E,0x42 },//
	{0x924F,0x00 },//
	{0x9250,0xE0 },//
	{0x9251,0x44 },//
	{0x9252,0x08 },//
	{0x9253,0xF0 },//
	{0x9254,0x22 },//
	{0x8504,0x39 },//
	{0x8505,0x17 },//
	{0x8506,0x00 },//
	{0x8507,0xF0 },//
	{0x8508,0x03 },//
	{0x850a,0x13 },//
	{0x850b,0x19 },//
	{0x850c,0x00 },//
	{0x850d,0x00 },//
	{0x850e,0x02 },//
	{0x8510,0x43 },//
	{0x8511,0x8B },//
	{0x8512,0x00 },//
	{0x8513,0x08 },//
	{0x8514,0x02 },//
	{0x8516,0x12 },//
	{0x8517,0x36 },//
	{0x8518,0x00 },//
	{0x8519,0x11 },//
	{0x851A,0x02 },//
	{0x851C,0x10 },//
	{0x851D,0x01 },//
	{0x851E,0x00 },//
	{0x851F,0x1D },//
	{0x8520,0x02 },//
	{0x8522,0x12 },//
	{0x8523,0x40 },//
	{0x8524,0x01 },//
	{0x8525,0x25 },//
	{0x8526,0x02 },//
	{0x8528,0x14 },//
	{0x8529,0x60 },//
	{0x852A,0x00 },//
	{0x852B,0xE4 },//
	{0x852C,0x00 },//
	{0x852E,0x15 },//
	{0x852F,0xA0 },//
	{0x8530,0x00 },//
	{0x8531,0xE2 },//
	{0x8532,0x00 },//
	{0x8534,0x0B },//
	{0x8535,0x55 },//
	{0x8536,0x01 },//
	{0x8537,0x28 },//
	{0x8538,0x02 },//
	{0x853A,0x12 },//
	{0x853B,0x80 },//
	{0x853C,0x01 },//
	{0x853D,0x3E },//
	{0x853E,0x02 },//
	{0x8540,0x3E },//
	{0x8541,0x29 },//
	{0x8542,0x01 },//
	{0x8543,0xD6 },//
	{0x8544,0x02 },//
	{0x8546,0x43 },//
	{0x8547,0x87 },//
	{0x8548,0x01 },//
	{0x8549,0xF7 },//
	{0x854A,0x02 },//
	{0x854c,0x45 },//
	{0x854d,0x08 },//
	{0x854e,0x02 },//
	{0x854f,0x13 },//
	{0x8550,0x02 },//
	{0x8552,0x4A },//
	{0x8553,0x87 },//
	{0x8554,0x02 },//
	{0x8555,0x41 },//
	{0x8556,0x02 },//
	{0x8500,0x01 },//		;Enable Ram and disable Write;
	{0xffff,0x00 },//		;MCU Reset;//delay200
	{REG_DLY,200},
	{0x0101,0x03 },//; Rotate
	{0x0112,0x0A },//
	{0x0113,0x0A },//
	{0x0111,0x02 },//
	{0x0304,0x00 },//
	{0x0305,0x02 },//
	{0x0306,0x00 },//
	{0x0307,0x44 },//
	{0x0302,0x00 },//
	{0x0303,0x05 },//
	{0x0300,0x00 },//
	{0x0301,0x01 },//
	{0x0200,0x02 },//
	{0x0201,0xB0 },//
	{0x0202,0x01 },//
	{0x0203,0x90 },//
	{0x0204,0x00 },//
	{0x0205,0x60 },//
	{0x3020,0x0F },//
	{0x801A,0x05 },//
	{0x8023,0x11 },//
	{0x8027,0x11 },//
	{0x8011,0x06 },//
	{0x5300,0x01 },//
	{0x5318,0x0C },//
	{0x5319,0xE0 },//
	{0x531C,0x09 },//
	{0x531D,0xB0 },//
	{0x5320,0x0C },//
	{0x5321,0xE0 },//
	{0x5324,0x09 },//
	{0x5325,0xB0 },//
	{0xA649,0x01 },//
	{0x0380,0x00 },//
	{0x0381,0x01 },//
	{0x0382,0x00 },//
	{0x0383,0x01 },//
	{0x0384,0x00 },//
	{0x0385,0x01 },//
	{0x0386,0x00 },//
	{0x0387,0x03 },//
	{0x0344,0x00 },//
	{0x0345,0x00 },//
	{0x0348,0x0C },//
	{0x0349,0xDF },//
	{0x0346,0x00 },//
	{0x0347,0x00 },//
	{0x034A,0x09 },//
	{0x034B,0xAF },//
	{0x034C,0x05 },//
	{0x034D,0x00 },//
	{0x034E,0x02 },//
	{0x034F,0xD0 },//
	{0xA608,0x04 },// Load Bruce Data from OTP
	{0xA607,0x01 },//
	{0x0100,0x01 },//
};


/*
 * Here we'll try to encapsulate the changes for just the output
 * video format.
 * 
 */

static struct regval_list sensor_fmt_raw[] = {

};

/*
 * On most platforms, we'd rather do straight i2c I/O.
 */
static int sensor_read(struct v4l2_subdev *sd, unsigned short reg,
    unsigned char *value)
{
	int ret=0;
	int cnt=0;
	
	ret = cci_read_a16_d8(sd,reg,value);
	while(ret!=0&&cnt<2)
	{
		ret = cci_read_a16_d8(sd,reg,value);
		cnt++;
	}
	if(cnt>0)
		vfe_dev_dbg("sensor read retry=%d\n",cnt);
  
	return ret;
}

static int sensor_write(struct v4l2_subdev *sd, unsigned short reg,
    unsigned char value)
{
	int ret=0;
	int cnt=0;
	
	ret = cci_write_a16_d8(sd,reg,value);
	while(ret!=0&&cnt<2)
	{
		ret = cci_write_a16_d8(sd,reg,value);
		cnt++;
	}
	if(cnt>0)
		vfe_dev_dbg("sensor write retry=%d\n",cnt);
  
	return ret;
}

/*
 * Write a list of register settings;
 */
static int sensor_write_array(struct v4l2_subdev *sd, struct regval_list *regs, int array_size)
{
	int i=0;
  
	if(!regs)
		return -EINVAL;
  
	while(i<array_size)
	{
		if(regs->addr == REG_DLY) {
			msleep(regs->data);
		} else {  
			//printk("write 0x%x=0x%x\n", regs->addr, regs->data);
			LOG_ERR_RET(sensor_write(sd, regs->addr, regs->data))
		}
		i++;
		regs++;
	}
	return 0;
}
static int sensor_s_exp_gain(struct v4l2_subdev *sd, struct sensor_exp_gain *exp_gain)
{ 
	int exp_val, gain_val;
	unsigned char explow=0,expmid=0;
	unsigned char gainlow=0;  
	struct sensor_info *info = to_state(sd);
	exp_val = exp_gain->exp_val;
	gain_val = exp_gain->gain_val;
	if(exp_val>0xfffff)
		exp_val=0xfffff;
	expmid  = (unsigned char) ( (0x0ff000&exp_val)>>12); 
	explow  = (unsigned char) ( (0x000ff0&exp_val)>>4);
	if(gain_val > 0x0ff)
		gain_val = 0x0ff;
	gainlow = (unsigned char)(gain_val);
	sensor_write(sd, 0x0104, 0x01); 
	sensor_write(sd, 0x0205, gainlow);  
	sensor_write(sd, 0x0202, expmid);
	sensor_write(sd, 0x0203, explow);	
	sensor_write(sd, 0x0104, 0x00); 
	printk("exp=%d,gain=%d\n",expmid*256+explow,gainlow);
	info->exp = exp_val;
	info->gain = gain_val;
	return 0;
}

static int sensor_g_exp(struct v4l2_subdev *sd, __s32 *value)
{
	struct sensor_info *info = to_state(sd);
  
	*value = info->exp;
	vfe_dev_dbg("sensor_get_exposure = %d\n", info->exp);
	return 0;
}

static int sensor_s_exp(struct v4l2_subdev *sd, unsigned int exp_val)
{ 
	unsigned char explow,expmid;
	struct sensor_info *info = to_state(sd);

	if(exp_val>0xfffff)
		exp_val=0xfffff;
	expmid  = (unsigned char) ( (0x0ff000&exp_val)>>12); 
	explow  = (unsigned char) ( (0x000ff0&exp_val)>>4);
	sensor_write(sd, 0x0202, expmid);
	sensor_write(sd, 0x0203, explow);	

	info->exp = exp_val;
	return 0;
}

static int sensor_g_gain(struct v4l2_subdev *sd, __s32 *value)
{
	struct sensor_info *info = to_state(sd);
  
	*value = info->gain;
	return 0;
}

static int sensor_s_gain(struct v4l2_subdev *sd, int gain_val)
{
	unsigned char gainlow=0;
	struct sensor_info *info = to_state(sd);
	if(gain_val > 0x1ff)
		gain_val = 0x1ff;
	gainlow = (unsigned char)(gain_val);
	sensor_write(sd, 0x0205, gainlow);  
	info->gain = gain_val;

	return 0;
}


/*
 * Stuff that knows about the sensor.
 */
 
static int sensor_power(struct v4l2_subdev *sd, int on)
{
	switch(on)
	{
		case CSI_SUBDEV_STBY_ON:
			vfe_dev_dbg("CSI_SUBDEV_STBY_ON!\n");
			cci_lock(sd);    
			vfe_gpio_write(sd,PWDN,0);
			usleep_range(10000,11000);
			usleep_range(10000,11000);
			cci_unlock(sd);  
			vfe_set_mclk(sd,OFF);
			break;
		case CSI_SUBDEV_STBY_OFF:
			vfe_dev_dbg("CSI_SUBDEV_STBY_OFF!\n");
			cci_lock(sd);    
			vfe_set_mclk_freq(sd,MCLK);
			vfe_set_mclk(sd,ON);
			usleep_range(10000,11000);
			cci_unlock(sd);        
			vfe_gpio_write(sd,PWDN,1);
			usleep_range(10000,11000);
			break;
		case CSI_SUBDEV_PWR_ON:
			vfe_dev_dbg("CSI_SUBDEV_PWR_ON!\n");
			cci_lock(sd);    
			vfe_gpio_set_status(sd,PWDN,1);//set the gpio to output
			vfe_gpio_set_status(sd,RESET,1);//set the gpio to output
			vfe_gpio_write(sd,RESET,0);
			vfe_gpio_write(sd,PWDN,0);
			usleep_range(1000,1100);
			vfe_set_mclk_freq(sd,MCLK);
			vfe_set_mclk(sd,ON);
			usleep_range(10000,11000);
			// vfe_gpio_write(sd,POWER_EN,CSI_GPIO_HIGH);
			vfe_set_pmu_channel(sd,IOVDD,ON);
			vfe_set_pmu_channel(sd,AVDD,ON);
			vfe_set_pmu_channel(sd,DVDD,ON);
			vfe_set_pmu_channel(sd,AFVDD,ON);
			vfe_gpio_write(sd,PWDN,1);
			usleep_range(10000,11000);
			vfe_gpio_write(sd,RESET,1);
			usleep_range(30000,31000);
			cci_unlock(sd);  
			break;
		case CSI_SUBDEV_PWR_OFF:
			vfe_dev_dbg("CSI_SUBDEV_PWR_OFF!\n");
			cci_lock(sd);    
			vfe_set_mclk(sd,OFF);
			//  vfe_gpio_write(sd,POWER_EN,CSI_GPIO_LOW);
			vfe_gpio_write(sd,RESET,0);
			vfe_set_pmu_channel(sd,AFVDD,OFF);
			vfe_set_pmu_channel(sd,DVDD,OFF);
			vfe_set_pmu_channel(sd,AVDD,OFF);
			vfe_set_pmu_channel(sd,IOVDD,OFF);  
			usleep_range(10000,11000);
			// vfe_gpio_write(sd,POWER_EN,CSI_GPIO_LOW);
			vfe_gpio_write(sd,PWDN,0);
			usleep_range(10000,11000);
			vfe_gpio_set_status(sd,RESET,0);//set the gpio to input
			vfe_gpio_set_status(sd,PWDN,0);//set the gpio to input
			cci_unlock(sd);  
			break;
		default:
			return -EINVAL;
	}   

	return 0;
}
 
static int sensor_reset(struct v4l2_subdev *sd, u32 val)
{ 
	return 0;
	switch(val)
	{
		case 0:
			vfe_gpio_write(sd,PWDN,1);
			usleep_range(10000,11000);
			break;
		case 1:
			vfe_gpio_write(sd,PWDN,0);
			usleep_range(10000,11000);
			break;
		default:
			return -EINVAL;
	}

	return 0;
}

static int sensor_detect(struct v4l2_subdev *sd)
{
	unsigned char rdval;
    LOG_ERR_RET(sensor_read(sd, 0x0000, &rdval))
	if((rdval&0x0f) != 0x0a)
		return -ENODEV;
	LOG_ERR_RET(sensor_read(sd, 0x0001, &rdval))
	if(rdval != 0x64)
		return -ENODEV;
	printk("find the hm8030 ***********\n");
	return 0;
}

static int sensor_init(struct v4l2_subdev *sd, u32 val)
{
	int ret;
	struct sensor_info *info = to_state(sd);

	vfe_dev_dbg("sensor_init\n");

	/*Make sure it is a target sensor*/
	ret = sensor_detect(sd);
	if (ret) {
		vfe_dev_err("chip found is not an target chip.\n");
		return ret;
	}

	vfe_get_standby_mode(sd,&info->stby_mode);

	if((info->stby_mode == HW_STBY || info->stby_mode == SW_STBY) \
			&& info->init_first_flag == 0) {
		vfe_dev_print("stby_mode and init_first_flag = 0\n");
		return 0;
	}

	info->focus_status = 0;
	info->low_speed = 0;
	info->width = HXGA_WIDTH;
	info->height = HXGA_HEIGHT;
	info->hflip = 0;
	info->vflip = 0;
	info->gain = 0;

	info->tpf.numerator = 1;            
	info->tpf.denominator = 30;    /* 30fps */    
  
	ret = sensor_write_array(sd, sensor_default_regs, ARRAY_SIZE(sensor_default_regs));  
	if(ret < 0) {
		vfe_dev_err("write sensor_default_regs error\n");
		return ret;
	}

	if(info->stby_mode == 0)
		info->init_first_flag = 0;

	info->preview_first_flag = 1;

	return 0;
}

static long sensor_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{
	int ret=0;
	struct sensor_info *info = to_state(sd);
	switch(cmd) {
		case GET_CURRENT_WIN_CFG:
			if(info->current_wins != NULL)
			{
				memcpy( arg,
				        info->current_wins,
				        sizeof(struct sensor_win_size) );
				ret=0;
			}
			else
			{
				vfe_dev_err("empty wins!\n");
				ret=-1;
			}
			break;
		case SET_FPS:
			break;
		case ISP_SET_EXP_GAIN:
			sensor_s_exp_gain(sd, (struct sensor_exp_gain *)arg);
			break;
		default:
			return -EINVAL;
	}
	return ret;
}


/*
 * Store information about the video data format. 
 */
static struct sensor_format_struct {
	__u8 *desc;
	//__u32 pixelformat;
	enum v4l2_mbus_pixelcode mbus_code;
	struct regval_list *regs;
	int regs_size;
	int bpp;   /* Bytes per pixel */
}sensor_formats[] = {
	{
		.desc   = "Raw RGB Bayer",
		.mbus_code  = V4L2_MBUS_FMT_SGBRG10_10X1,
		.regs     = sensor_fmt_raw,
		.regs_size = ARRAY_SIZE(sensor_fmt_raw),
		.bpp    = 1
	},
};
#define N_FMTS ARRAY_SIZE(sensor_formats)

  

/*
 * Then there is the issue of window sizes.  Try to capture the info here.
 */


static struct sensor_win_size sensor_win_sizes[] = {
#if 1
	/* 3280*2464 */
	{
		.width      = 3264,//3280,
		.height     = 2448,//2464,
		.hoffset    = 0,
		.voffset    = 0,
		.hts        = 2480,//4352,//3448,//4037,
		.vts        = 0x9ec,//4037,//2757,//4037,
		.pclk       = 94*1000*1000+500*1000,//252*1000*1000,
		.mipi_bps   = 662*1000*1000,
		.intg_min   = 1<<4,
		.intg_max   = 2540<<4,
		.gain_min   = 16,
		.gain_max   = 11<<4,
		.regs       = sensor_hxga_regs,
		.regs_size  = ARRAY_SIZE(sensor_hxga_regs),
		.set_size   = NULL,
	},

	/* 1080P */
	{
		.width	  = 1280,
		.height 	  = 720,
		.hoffset    = 0,
		.voffset    = 0,
		.hts		  = 2480,
		.vts		  = 2540,
		.pclk 	  = 94*1000*1000,
		.mipi_bps   = 400*1000*1000,
		.fps_fixed  = 1,
		.bin_factor = 1,
		.intg_min   = 1<<4,
		.intg_max   = 2540<<4,
		.gain_min   = 16,
		.gain_max   = 11<<4,
		.regs       = sensor_1080p_regs,//
		.regs_size  = ARRAY_SIZE(sensor_1080p_regs),//
		.set_size	  = NULL,
	},
#endif  
};

#define N_WIN_SIZES (ARRAY_SIZE(sensor_win_sizes))

static int sensor_enum_fmt(struct v4l2_subdev *sd, unsigned index,
                 enum v4l2_mbus_pixelcode *code)
{
	if (index >= N_FMTS)
		return -EINVAL;

	*code = sensor_formats[index].mbus_code;
	return 0;
}

static int sensor_enum_size(struct v4l2_subdev *sd,
                            struct v4l2_frmsizeenum *fsize)
{
	if(fsize->index > N_WIN_SIZES-1)
		return -EINVAL;
  
	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
	fsize->discrete.width = sensor_win_sizes[fsize->index].width;
	fsize->discrete.height = sensor_win_sizes[fsize->index].height;
  
	return 0;
}


static int sensor_try_fmt_internal(struct v4l2_subdev *sd,
    struct v4l2_mbus_framefmt *fmt,
    struct sensor_format_struct **ret_fmt,
    struct sensor_win_size **ret_wsize)
{
	int index;
	struct sensor_win_size *wsize;
	struct sensor_info *info = to_state(sd);

	for (index = 0; index < N_FMTS; index++)
		if (sensor_formats[index].mbus_code == fmt->code)
			break;

	if (index >= N_FMTS)
		return -EINVAL;

	if (ret_fmt != NULL)
		*ret_fmt = sensor_formats + index;

	/*
	* Fields: the sensor devices claim to be progressive.
	*/
	fmt->field = V4L2_FIELD_NONE;

	/*
	* Round requested image size down to the nearest
	* we support, but not below the smallest.
	*/
	for (wsize = sensor_win_sizes; wsize < sensor_win_sizes + N_WIN_SIZES; wsize++)
		if (fmt->width >= wsize->width && fmt->height >= wsize->height)
			break;

	if (wsize >= sensor_win_sizes + N_WIN_SIZES)
		wsize--;   /* Take the smallest one */
	if (ret_wsize != NULL)
		*ret_wsize = wsize;
	/*
	* Note the size we'll actually handle.
	*/
	fmt->width = wsize->width;
	fmt->height = wsize->height;
	info->current_wins = wsize;
	return 0;
}

static int sensor_try_fmt(struct v4l2_subdev *sd, 
             struct v4l2_mbus_framefmt *fmt)
{
	return sensor_try_fmt_internal(sd, fmt, NULL, NULL);
}

static int sensor_g_mbus_config(struct v4l2_subdev *sd,
           struct v4l2_mbus_config *cfg)
{
	cfg->type = V4L2_MBUS_CSI2;
	cfg->flags = 0|V4L2_MBUS_CSI2_2_LANE|V4L2_MBUS_CSI2_CHANNEL_0;
  
	return 0;
}


/*
 * Set a format.
 */
static int sensor_s_fmt(struct v4l2_subdev *sd, 
             struct v4l2_mbus_framefmt *fmt)
{
	int ret;
	struct sensor_format_struct *sensor_fmt;
	struct sensor_win_size *wsize;
	struct sensor_info *info = to_state(sd);
  
	vfe_dev_dbg("sensor_s_fmt\n");
  
	ret = sensor_try_fmt_internal(sd, fmt, &sensor_fmt, &wsize);
	if (ret)
		return ret;

  

	sensor_write_array(sd, sensor_fmt->regs, sensor_fmt->regs_size);

	ret = 0;
	if (wsize->regs)
		LOG_ERR_RET(sensor_write_array(sd, wsize->regs, wsize->regs_size))
  
	if (wsize->set_size)
		LOG_ERR_RET(wsize->set_size(sd))

	info->fmt = sensor_fmt;
	info->width = wsize->width;
	info->height = wsize->height;
	hm8030_sensor_vts = wsize->vts;
	vfe_dev_print("s_fmt set width = %d, height = %d\n",wsize->width,wsize->height);

	if(info->capture_mode == V4L2_MODE_VIDEO)
	{
	//video
	} else {
	//capture image
	}
   
	vfe_dev_print("s_fmt end\n");
	return 0;
}

/*
 * Implement G/S_PARM.  There is a "high quality" mode we could try
 * to do someday; for now, we just do the frame rate tweak.
 */
static int sensor_g_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
{
	struct v4l2_captureparm *cp = &parms->parm.capture;
	struct sensor_info *info = to_state(sd);

	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
  
	memset(cp, 0, sizeof(struct v4l2_captureparm));
	cp->capability = V4L2_CAP_TIMEPERFRAME;
	cp->capturemode = info->capture_mode;
     
	return 0;
}

static int sensor_s_parm(struct v4l2_subdev *sd, struct v4l2_streamparm *parms)
{
	struct v4l2_captureparm *cp = &parms->parm.capture;
	struct sensor_info *info = to_state(sd);
  
	vfe_dev_dbg("sensor_s_parm\n");
  
	if (parms->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
		return -EINVAL;
  
	if (info->tpf.numerator == 0)
		return -EINVAL;
    
	info->capture_mode = cp->capturemode;
  
	return 0;
}


static int sensor_queryctrl(struct v4l2_subdev *sd,
    struct v4l2_queryctrl *qc)
{
	/* Fill in min, max, step and default value for these controls. */
	/* see include/linux/videodev2.h for details */

	switch (qc->id) {
	case V4L2_CID_GAIN:
		return v4l2_ctrl_query_fill(qc, 1*16, 11*16, 1, 1*16);
	case V4L2_CID_EXPOSURE:
		return v4l2_ctrl_query_fill(qc, 0, 65535*16, 1, 16);
	case V4L2_CID_FRAME_RATE:
		return v4l2_ctrl_query_fill(qc, 15, 120, 1, 120);
	}
	return -EINVAL;
}

static int sensor_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	switch (ctrl->id) {
	case V4L2_CID_GAIN:
		return sensor_g_gain(sd, &ctrl->value);
	case V4L2_CID_EXPOSURE:
		return sensor_g_exp(sd, &ctrl->value);
	}
	return -EINVAL;
}

static int sensor_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	struct v4l2_queryctrl qc;
	int ret;

	qc.id = ctrl->id;
	ret = sensor_queryctrl(sd, &qc);
	if (ret < 0) {
		return ret;
	}

	if (ctrl->value < qc.minimum || ctrl->value > qc.maximum) {
		vfe_dev_err("max gain qurery is %d,min gain qurey is %d\n",qc.maximum,qc.minimum);
		return -ERANGE;
	}

	switch (ctrl->id) {
	case V4L2_CID_GAIN:
		return sensor_s_gain(sd, ctrl->value);
	case V4L2_CID_EXPOSURE:
		return sensor_s_exp(sd, ctrl->value);
	}
	return -EINVAL;
}


static int sensor_g_chip_ident(struct v4l2_subdev *sd,
    struct v4l2_dbg_chip_ident *chip)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);

	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SENSOR, 0);
}


/* ----------------------------------------------------------------------- */

static const struct v4l2_subdev_core_ops sensor_core_ops = {
	.g_chip_ident = sensor_g_chip_ident,
	.g_ctrl = sensor_g_ctrl,
	.s_ctrl = sensor_s_ctrl,
	.queryctrl = sensor_queryctrl,
	.reset = sensor_reset,
	.init = sensor_init,
	.s_power = sensor_power,
	.ioctl = sensor_ioctl,
};

static const struct v4l2_subdev_video_ops sensor_video_ops = {
	.enum_mbus_fmt = sensor_enum_fmt,
	.enum_framesizes = sensor_enum_size,
	.try_mbus_fmt = sensor_try_fmt,
	.s_mbus_fmt = sensor_s_fmt,
	.s_parm = sensor_s_parm,
	.g_parm = sensor_g_parm,
	.g_mbus_config = sensor_g_mbus_config,
};

static const struct v4l2_subdev_ops sensor_ops = {
	.core = &sensor_core_ops,
	.video = &sensor_video_ops,
};

/* ----------------------------------------------------------------------- */
static struct cci_driver cci_drv = {
	.name = SENSOR_NAME,
	.addr_width = CCI_BITS_16,
	.data_width = CCI_BITS_8,
};

static int sensor_probe(struct i2c_client *client,
      const struct i2c_device_id *id)
{
	struct v4l2_subdev *sd;
	struct sensor_info *info;
	info = kzalloc(sizeof(struct sensor_info), GFP_KERNEL);
	if (info == NULL)
		return -ENOMEM;
	sd = &info->sd;
	glb_sd = sd;
	cci_dev_probe_helper(sd, client, &sensor_ops, &cci_drv);

	info->fmt = &sensor_formats[0];
	info->af_first_flag = 1;
	info->init_first_flag = 1;

	return 0;
}
static int sensor_remove(struct i2c_client *client)
{
	struct v4l2_subdev *sd;
	sd = cci_dev_remove_helper(client, &cci_drv);
	kfree(to_state(sd));
	return 0;
}

static const struct i2c_device_id sensor_id[] = {
	{SENSOR_NAME, 0 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, sensor_id);


static struct i2c_driver sensor_driver = {
	.driver = {
		.owner = THIS_MODULE,
		.name = SENSOR_NAME,
	},
	.probe = sensor_probe,
	.remove = sensor_remove,
	.id_table = sensor_id,
};
static __init int init_sensor(void)
{
	return cci_dev_init_helper(&sensor_driver);
}

static __exit void exit_sensor(void)
{
	cci_dev_exit_helper(&sensor_driver);
}

module_init(init_sensor);
module_exit(exit_sensor);

